package org.lzx.converter.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.Date;
import java.util.LinkedList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.lzx.converter.ParseLzx;
import org.lzx.converter.util.ReplaceString;

/**
 * 
 * @author swagner
 * @date 29.06.2008
 *
 */
public class GenerateClassStructure {
	
	public static final String confDirName = "classNames.xml";
	public static LinkedList<String> currentClassNameList = new LinkedList();
	
	private static final Log log = LogFactory.getLog(GenerateClassStructure.class);
	
	private String currentAdditionalFilePath = "input/";
	
	private String currentoutputFilePath = "output/";

	public GenerateClassStructure() {
		try {
			
			//Some base classes
			//TODO: auto parse this List
			currentClassNameList.add("drawview");
			
			File dir_input = new File("input/");
			log.debug("Absoulte Path: "+dir_input.getAbsolutePath());
			File dir_output = new File("output/");
			
			
			//This Generates the Class-Names List
			this.generateClassByFilesFolders(dir_input);
			
			File dir_conf = new File("conf/");
			
			log.debug("Absoulte Path Conf: "+dir_conf.getAbsolutePath());
			CreateClassFile.getInstance().createConfFile(dir_conf, currentClassNameList);
			
			
			//Parse Through LZX and replace + generate the File Structure
			this.parseThroughFolders(dir_input, dir_output);
			
		} catch (Exception err) {
			log.error("[GenerateClassStructure]",err);
		}
	}
	
	public static void main(String args[]) {
		try {
			new GenerateClassStructure();
		} catch (Exception err) {
			err.printStackTrace();
		}
	}
	
	/**
	 * 
	 * @param dir
	 * @throws Exception
	 */
	public void generateClassByFilesFolders(File dir) throws Exception{
		if (dir.exists() && dir.isDirectory()) {
			
			String workingDir = dir.getAbsolutePath();
			
			FilenameFilter ff2 = new FilenameFilter() {
			     public boolean accept(File b, String name) {
			    	  String absPath = b.getAbsolutePath()+File.separatorChar+name;
			    	  File f = new File (absPath);
			    	  if (f.isFile() && f.getName().endsWith(".lzx")) {
			    		  return true;
			    	  } else {
//			    		  if (f.getName().startsWith(".")){
//			    			  return false;
//			    		  }
			    		  return false;
			    	  }
			     }
			};
			
			String[] allfiles = dir.list(ff2);			
			if(allfiles!=null && allfiles.length!=0){
				
				for(int i=0; i<allfiles.length; i++){
					//File file = new File(working_dir+File.separatorChar+allfiles[i]);
					//log.debug("File: "+allfiles[i]);
					File newFile = new File(workingDir+File.separatorChar+allfiles[i]);
					ParseLzx.getInstance().parse(newFile);
				}
				
			}
			
			//Goto Folders and generate 
			//First get all Directories of this Folder
			FilenameFilter ff = new FilenameFilter() {
			     public boolean accept(File b, String name) {
			    	  String absPath = b.getAbsolutePath()+File.separatorChar+name;
			    	  File f = new File (absPath);
			    	  //return f.isDirectory();
			          if (f.isDirectory()){
			        	  if (f.getName().startsWith(".")){
			        		  return false;
			        	  } else {
			        		  return true;
			        	  }
			          } else {
			        	  return false;
			          }
			     }
			};	
			
			String[] allfolders = dir.list(ff);
			if(allfolders!=null && allfolders.length!=0){
				for(int i=0; i<allfolders.length; i++){
					//log.debug("Folder: "+allfolders[i]);
					File newDir = new File(workingDir+File.separatorChar+allfolders[i]);
					this.generateClassByFilesFolders(newDir);
				}
			}
			
		}
	}
	
	/**
	 * 
	 * @param dir
	 * @param dir_output
	 * @throws Exception
	 */
	public void parseThroughFolders(File dir, File dir_output) throws Exception{
		if (dir.exists() && dir.isDirectory()) {
			
			String workingDir = dir.getAbsolutePath();
			String outputDir = dir_output.getAbsolutePath();
			
			FilenameFilter ff2 = new FilenameFilter() {
			     public boolean accept(File b, String name) {
			    	  String absPath = b.getAbsolutePath()+File.separatorChar+name;
			    	  File f = new File (absPath);
			    	  if (f.isFile()) {
//			    		  if (f.getName().startsWith(".")){
//			    			  return false;
//			    		  }
			    		  return true;
			    	  } else {
			    		  
			    		  return false;
			    	  }
			     }
			};
			
			String[] allfiles = dir.list(ff2);			
			if(allfiles!=null && allfiles.length!=0){
				
				for(int i=0; i<allfiles.length; i++){
					//File file = new File(working_dir+File.separatorChar+allfiles[i]);
					//log.debug("File: "+allfiles[i]);
					
					File newFile = new File(workingDir+File.separatorChar+allfiles[i]);
					File outputFile = new File (dir_output.getAbsolutePath()+File.separatorChar+newFile.getName());
					
					if (allfiles[i].endsWith(".lzx")) {
						//Parse and replace File
						ReplaceString.getInstance().processFile(newFile, outputFile);
					} else {
						//just copy to output dir
						this.copyFile(newFile,outputFile);
					}
				}
				
			}
			
			//Goto Folders and generate 
			//First get all Directories of this Folder
			FilenameFilter ff = new FilenameFilter() {
			     public boolean accept(File b, String name) {
			    	  String absPath = b.getAbsolutePath()+File.separatorChar+name;
			    	  File f = new File (absPath);
			    	  //return f.isDirectory();
			          if (f.isDirectory()){
			        	  if (f.getName().startsWith(".")){
			        		  return false;
			        	  } else {
			        		  return true;
			        	  }
			          } else {
			        	  return false;
			          }
			     }
			};	
			
			String[] allfolders = dir.list(ff);
			if(allfolders!=null && allfolders.length!=0){
				for(int i=0; i<allfolders.length; i++){
					//log.debug("Folder: "+allfolders[i]);
					File newDir = new File(workingDir+File.separatorChar+allfolders[i]);
					
					File newOut = new File(outputDir+File.separatorChar+allfolders[i]);
					if (newOut.exists()) {
						newOut.delete();
					}
					newOut.mkdir();
					this.parseThroughFolders(newDir,newOut);
				}
			}
			
		}
	}
	
	
	public void copyFile(File in, File out) throws Exception {
	    FileInputStream fis  = new FileInputStream(in);
	    FileOutputStream fos = new FileOutputStream(out);
	    try {
	        byte[] buf = new byte[1024];
	        int i = 0;
	        while ((i = fis.read(buf)) != -1) {
	            fos.write(buf, 0, i);
	        }
	    } 
	    catch (Exception e) {
	        throw e;
	    }
	    finally {
	        if (fis != null) fis.close();
	        if (fos != null) fos.close();
	    }
	  }

}
